using Unity.Netcode;
using UnityEngine;
using System.Collections.Generic;

namespace Since.Netcode
{
	[DisallowMultipleComponent]
	public class NetcodeTransform : NetworkBehaviourPro<NetcodeTransform, NetcodeTransformServer, NetcodeTransformClient, NetcodeTransformClientSimulate, NetcodeTransformAuthority, NetcodeTransformNonAuthority>
	{
		public bool useSmoothing = true; // 是否使用平滑校正
		public float positionErrorThreshold = 1f; // 位置误差阈值，超过此值才校正
		public float positionThreshold = 0.01f; // 位置变化阈值，小于此值不同步

		// 使用Vector2替代Vector3来减少数据传输量，只传输XY轴
		public NetworkVariable<Vector2> _Position = new NetworkVariable<Vector2>(Vector2.zero,
			NetworkVariableReadPermission.Everyone,
			NetworkVariableWritePermission.Owner);

		public NetworkVariable<Vector2> _Velocity = new NetworkVariable<Vector2>(Vector2.zero,
			NetworkVariableReadPermission.Everyone,
			NetworkVariableWritePermission.Owner);

		// 缓存上一次的值用于比较是否有足够变化
		private Vector2 _lastSyncedPosition;
		private Vector2 _lastSyncedVelocity;

		// 将Vector2转回Vector3
		public Vector3 NetworkPosition
		{
			get { return new Vector3(_Position.Value.x, _Position.Value.y, 0f); }
		}

		public Vector3 NetworkVelocity
		{
			get { return new Vector3(_Velocity.Value.x, _Velocity.Value.y, 0f); }
		}

		// 更新网络位置（只在有显著变化时更新）
		public void UpdateNetworkPosition(Vector3 position)
		{
			if (!IsOwner) return;

			Vector2 newPos = new Vector2(position.x, position.y);

			// 检查是否有足够变化才更新，减少网络消息
			if (Vector2.Distance(newPos, _lastSyncedPosition) > positionThreshold)
			{
				_Position.Value = newPos;
				_lastSyncedPosition = newPos;
			}
		}

		// 更新网络速度（只在有显著变化时更新）
		public void UpdateNetworkVelocity(Vector3 velocity)
		{
			if (!IsOwner) return;

			Vector2 newVel = new Vector2(velocity.x, velocity.y);

			_Velocity.Value = newVel;
			_lastSyncedVelocity = newVel;
			
		}

		public void SyncState()
		{
			if(!IsSpawned)
				return;
			if (Authority == E_NetcodeAuthority.Client)
			{
				UpdateTransformServerRpc(_Position.Value, _Velocity.Value);
			}
			else
			{
				UpdateTransformClientRpc(_Position.Value, _Velocity.Value);
			}
		}
		
		public void SyncVelocity()
		{
			if (!IsSpawned)
				return;
			if (Authority == E_NetcodeAuthority.Client)
			{
				UpdateVelocityServerRpc(_Velocity.Value);
			}
			else
			{
				UpdateVelocityClientRpc(_Velocity.Value);
			}
		}

		[ServerRpc]
		private void UpdateVelocityServerRpc(Vector2 velocity)
		{
			// 通知非权威端
			Vector3 vel3D = new Vector3(velocity.x, velocity.y, 0f);

			NonAuthority?.OnVelocityValueChange(vel3D);

			UpdateVelocityClientRpc(velocity);
		}
		
		[ClientRpc]
		private void UpdateVelocityClientRpc(Vector2 velocity)
		{
			// 通知非权威端
			Vector3 vel3D = new Vector3(velocity.x, velocity.y, 0f);
			NonAuthority?.OnVelocityValueChange(vel3D);
		}

			[ServerRpc]
		public void UpdateTransformServerRpc(Vector2 position, Vector2 velocity, ServerRpcParams sendParams = default)
		{
			// 通知非权威端
			Vector3 pos3D = new Vector3(position.x, position.y, 0f);
			Vector3 vel3D = new Vector3(velocity.x, velocity.y, 0f);

			NonAuthority?.OnPositonValueChange(pos3D);
			NonAuthority?.OnVelocityValueChange(vel3D);

			UpdateTransformClientRpc(position, velocity);
		}

		[ClientRpc]
		public void UpdateTransformClientRpc(Vector2 position, Vector2 velocity)
		{
			// 通知非权威端
			Vector3 pos3D = new Vector3(position.x, position.y, 0f);
			Vector3 vel3D = new Vector3(velocity.x, velocity.y, 0f);
			NonAuthority?.OnPositonValueChange(pos3D);
			NonAuthority?.OnVelocityValueChange(vel3D);
		}

		public void SetVelocity(Vector3 velocity)
		{
			if (IsOwner)
			{
				UpdateNetworkVelocity(velocity);
				SyncVelocity();
			}
		}
	}
}
